package org.fuys.etp.repo.repository.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.fuys.etp.core.model.type.EtpTypeEnum;
import org.fuys.etp.core.model.vo.TpBaseConfigVO;
import org.fuys.etp.core.model.vo.TpConfigVO;
import org.fuys.etp.core.model.vo.TpDynamicConfigVO;
import org.fuys.etp.core.model.vo.TpFixedConfigVO;
import org.fuys.etp.repo.converter.PoToVoConverter;
import org.fuys.etp.repo.converter.VoToPoConverter;
import org.fuys.etp.repo.mapper.EtpBaseConfigMapper;
import org.fuys.etp.repo.mapper.EtpDynamicConfigMapper;
import org.fuys.etp.repo.mapper.EtpFixedConfigMapper;
import org.fuys.etp.repo.po.EtpBaseConfig;
import org.fuys.etp.repo.po.EtpDynamicConfig;
import org.fuys.etp.repo.po.EtpFixedConfig;
import org.fuys.etp.repo.repository.IEtpConfigRepository;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @projectName: fuys-etp
 * @package: org.fuys.etp.repo.repository.impl
 * @className: EtpConfigRepository
 * @author: WangJing
 * @description: 线程池配置仓储实现类
 * @date: 2025/2/6 23:37
 * @version: 1.0
 */
@Component
public class EtpConfigRepository implements IEtpConfigRepository {

    @Resource
    private EtpBaseConfigMapper baseConfigMapper;

    @Resource
    private EtpFixedConfigMapper fixedConfigMapper;

    @Resource
    private EtpDynamicConfigMapper dynamicConfigMapper;

    @Override
    public boolean insertConfig(String poolType, TpConfigVO tpConfig) {
        final TpBaseConfigVO baseConfig = tpConfig.getBaseConfig();
        final int baseConfigId = baseConfigMapper.insert(VoToPoConverter.converter(baseConfig));
        if(EtpTypeEnum.STAGE_SWITCH_THREAD_POOL_EXECUTOR.type().equals(poolType)){
            final TpFixedConfigVO fixedConfig = tpConfig.getFixedConfig();
            fixedConfig.setBaseConfigVersion(baseConfigId);
            fixedConfigMapper.insert(VoToPoConverter.converter(fixedConfig));
            return true;
        }else if(EtpTypeEnum.ADAPTIVE_THREAD_POOLS_EXECUTOR.type().equals(poolType)){
            final TpDynamicConfigVO dynamicConfig = tpConfig.getDynamicConfig();
            dynamicConfig.setBaseConfigVersion(baseConfigId);
            dynamicConfigMapper.insert(VoToPoConverter.converter(dynamicConfig));
            return true;
        }
        return false;
    }

    @Override
    public boolean updateConfig(String poolType, Integer configVersion, TpConfigVO config) {
        if(EtpTypeEnum.ADAPTIVE_THREAD_POOLS_EXECUTOR.type().equals(poolType)){
            if(config.getDynamicConfig()!=null){
                final EtpDynamicConfig converter = VoToPoConverter.converter(config.getDynamicConfig());
                dynamicConfigMapper.update(converter,
                        new LambdaUpdateWrapper<EtpDynamicConfig>().eq(EtpDynamicConfig::getDynamicVersion,
                                converter.getDynamicVersion()));
            }
        }else if(EtpTypeEnum.STAGE_SWITCH_THREAD_POOL_EXECUTOR.type().equals(poolType)){
            if(config.getFixedConfig()!=null){
                final EtpFixedConfig converter = VoToPoConverter.converter(config.getFixedConfig());
                fixedConfigMapper.update(converter,
                        new LambdaUpdateWrapper<EtpFixedConfig>().eq(EtpFixedConfig::getFixedVersion,converter.getFixedVersion()));
            }
        }
        if(config.getBaseConfig()!=null) {
            final EtpBaseConfig baseConfig = VoToPoConverter.converter(config.getBaseConfig());
            baseConfigMapper.update(baseConfig,new LambdaUpdateWrapper<EtpBaseConfig>().eq(EtpBaseConfig::getVersion
                    ,baseConfig.getVersion()));
            return true;
        }
        return false;
    }

    @Override
    public boolean deleteConfig(String poolType, Integer configVersion) {
        if(EtpTypeEnum.ADAPTIVE_THREAD_POOLS_EXECUTOR.type().equals(poolType)){
            final EtpDynamicConfig etpDynamicConfig = dynamicConfigMapper.selectOne(new LambdaQueryWrapper<EtpDynamicConfig>()
                    .select(EtpDynamicConfig::getBaseConfigVersion)
                    .eq(EtpDynamicConfig::getDynamicVersion, configVersion));
            if(etpDynamicConfig == null){
                return true;
            }
            baseConfigMapper.delete(new LambdaQueryWrapper<EtpBaseConfig>()
                    .eq(EtpBaseConfig::getVersion, etpDynamicConfig.getBaseConfigVersion()));
            dynamicConfigMapper.delete(new LambdaQueryWrapper<EtpDynamicConfig>()
                    .eq(EtpDynamicConfig::getDynamicVersion,etpDynamicConfig.getDynamicVersion()));
        }else if(EtpTypeEnum.STAGE_SWITCH_THREAD_POOL_EXECUTOR.type().equals(poolType)){
            final EtpFixedConfig etpFixedConfig = fixedConfigMapper.selectOne(new LambdaQueryWrapper<EtpFixedConfig>()
                    .select(EtpFixedConfig::getBaseConfigVersion)
                    .eq(EtpFixedConfig::getFixedVersion, configVersion));
            if(etpFixedConfig == null){
                return true;
            }
            baseConfigMapper.delete(new LambdaQueryWrapper<EtpBaseConfig>()
                    .eq(EtpBaseConfig::getVersion,etpFixedConfig.getBaseConfigVersion()));
            fixedConfigMapper.delete(new LambdaQueryWrapper<EtpFixedConfig>()
                    .eq(EtpFixedConfig::getFixedVersion,etpFixedConfig.getFixedVersion()));
        }else{
            baseConfigMapper.delete(new LambdaQueryWrapper<EtpBaseConfig>()
                    .eq(EtpBaseConfig::getVersion, configVersion));
        }
        return false;
    }

    @Override
    public List<TpConfigVO> selectConfigByIds(String poolType, List<Integer> loadConfigIds) {
        List<Integer> baseConfigIds = null;
        Map<Integer,TpConfigVO> tpConfigVOMap = new HashMap<>();
        if(EtpTypeEnum.STAGE_SWITCH_THREAD_POOL_EXECUTOR.type().equals(poolType)){
            final List<EtpFixedConfig> etpFixedConfigs = fixedConfigMapper
                    .selectList(new LambdaQueryWrapper<EtpFixedConfig>()
                    .in(EtpFixedConfig::getFixedVersion, loadConfigIds));
            if(ObjectUtils.isEmpty(etpFixedConfigs) || etpFixedConfigs.size()!=loadConfigIds.size()){
                throw new IllegalArgumentException("Fuys Etp:请检查线程池配置 获取到的数据库中配置为空 或数量不匹配 创建失败");
            }
            etpFixedConfigs.forEach(item->{
                TpConfigVO config = TpConfigVO.builder().fixedConfig(PoToVoConverter.convert(item)).build();
                config.setLoadLevel(config.getFixedConfig().getLoadRating());
                tpConfigVOMap.put(item.getBaseConfigVersion(),config);
            });
            baseConfigIds = etpFixedConfigs.stream().map(EtpFixedConfig::getBaseConfigVersion).collect(Collectors.toList());
        }else if(EtpTypeEnum.ADAPTIVE_THREAD_POOLS_EXECUTOR.type().equals(poolType)){
            final List<EtpDynamicConfig> etpDynamicConfigs = dynamicConfigMapper.selectList(new LambdaUpdateWrapper<EtpDynamicConfig>()
                    .in(EtpDynamicConfig::getDynamicVersion, loadConfigIds));
            if(ObjectUtils.isEmpty(etpDynamicConfigs) || etpDynamicConfigs.size()!=loadConfigIds.size()){
                throw new IllegalArgumentException("Fuys Etp:请检查线程池配置 获取到的数据库中配置为空 或数量不匹配 创建失败");
            }
            baseConfigIds = etpDynamicConfigs.stream().map(EtpDynamicConfig::getBaseConfigVersion).collect(Collectors.toList());
            etpDynamicConfigs.forEach(item->{
                TpConfigVO config = TpConfigVO.builder().dynamicConfig(PoToVoConverter.convert(item)).build();
                config.setLoadLevel(config.getDynamicConfig().getLoadLevel());
                tpConfigVOMap.put(item.getBaseConfigVersion(),config);
            });
        }
        if(ObjectUtils.isEmpty(baseConfigIds)){
            baseConfigIds = loadConfigIds;
        }
        final List<EtpBaseConfig> etpBaseConfigs = baseConfigMapper.selectList(new LambdaQueryWrapper<EtpBaseConfig>()
                .in(EtpBaseConfig::getVersion, baseConfigIds));
        if(ObjectUtils.isEmpty(etpBaseConfigs) || etpBaseConfigs.size()!=loadConfigIds.size()){
            throw new IllegalArgumentException("Fuys Etp:请检查线程池配置 获取到的数据库中配置为空 或数量不匹配 创建失败");
        }
        etpBaseConfigs.forEach(item->{
            tpConfigVOMap.compute(item.getVersion(),(k,v)->{
                if(v!=null){
                    v.setBaseConfig(PoToVoConverter.convert(item));
                    return v;
                }
                return TpConfigVO.builder().loadLevel(9)
                        .baseConfig(PoToVoConverter.convert(item)).build();
            });
        });
        return new ArrayList<>(tpConfigVOMap.values());
    }
}
